//---------------------------------------------------------------------------------
// Copyright (c) 2008 David Vescovi.  All rights reserved.
//
// PhyIO Read/Write any physical location
// including SOC registers
//
//---------------------------------------------------------------------------------
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;

namespace PhyIO
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Button btRead;
		private System.Windows.Forms.Button btWrite;
	
		private static Int32 CODE_IOCTL_PHY_ADR = 4005;
		
		private static Int32 FILE_DEVICE_HAL = 0x00000101;
		private static Int32 FILE_ANY_ACCESS = 0x0;
		private static Int32 METHOD_BUFFERED = 0x0;
		private System.Windows.Forms.TextBox tbAddressHI;
		private System.Windows.Forms.TextBox tbDataHI;
		private System.Windows.Forms.TextBox tbMaskHI;
		private System.Windows.Forms.TextBox tbAddressLO;
		private System.Windows.Forms.TextBox tbDataLO;
		private System.Windows.Forms.TextBox tbMaskLO;
		private System.Windows.Forms.Label lbAddress;
		private System.Windows.Forms.Label lbData;
		private System.Windows.Forms.Label lbMask;
		private System.Windows.Forms.VScrollBar vScrollBar1;
		private System.Windows.Forms.Label lbHI;
		private System.Windows.Forms.Label lbLO;

		private uint g_address = 0x00000000;
		private uint g_data =    0x00000000;
		private uint g_mask =    0x00000000;
		
		private static Int32 IOCTL_PHY_ADR = 
			((FILE_DEVICE_HAL) << 16) | ((FILE_ANY_ACCESS) << 14) 
			| ((CODE_IOCTL_PHY_ADR) << 2) | (METHOD_BUFFERED);

		[DllImport("coredll.dll", SetLastError=true)]
		private static extern bool KernelIoControl(Int32 dwIoControlCode, byte[] lpInBuf, Int32 nInBufSize,
			byte[] lpOutBuf, Int32 nOutBufSize, ref Int32 lpBytesReturned);

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			base.Dispose( disposing );
		}
		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.btRead = new System.Windows.Forms.Button();
            this.btWrite = new System.Windows.Forms.Button();
            this.tbAddressHI = new System.Windows.Forms.TextBox();
            this.tbDataHI = new System.Windows.Forms.TextBox();
            this.tbMaskHI = new System.Windows.Forms.TextBox();
            this.tbAddressLO = new System.Windows.Forms.TextBox();
            this.tbDataLO = new System.Windows.Forms.TextBox();
            this.tbMaskLO = new System.Windows.Forms.TextBox();
            this.lbAddress = new System.Windows.Forms.Label();
            this.lbData = new System.Windows.Forms.Label();
            this.lbMask = new System.Windows.Forms.Label();
            this.vScrollBar1 = new System.Windows.Forms.VScrollBar();
            this.lbHI = new System.Windows.Forms.Label();
            this.lbLO = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // btRead
            // 
            this.btRead.Location = new System.Drawing.Point(24, 168);
            this.btRead.Name = "btRead";
            this.btRead.Size = new System.Drawing.Size(72, 24);
            this.btRead.TabIndex = 13;
            this.btRead.Text = "READ";
            this.btRead.Click += new System.EventHandler(this.btRead_Click);
            // 
            // btWrite
            // 
            this.btWrite.Location = new System.Drawing.Point(136, 168);
            this.btWrite.Name = "btWrite";
            this.btWrite.Size = new System.Drawing.Size(72, 24);
            this.btWrite.TabIndex = 12;
            this.btWrite.Text = "WRITE";
            this.btWrite.Click += new System.EventHandler(this.btWrite_Click);
            // 
            // tbAddressHI
            // 
            this.tbAddressHI.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.tbAddressHI.Location = new System.Drawing.Point(104, 24);
            this.tbAddressHI.MaxLength = 4;
            this.tbAddressHI.Name = "tbAddressHI";
            this.tbAddressHI.Size = new System.Drawing.Size(48, 26);
            this.tbAddressHI.TabIndex = 11;
            this.tbAddressHI.Text = "0000";
            // 
            // tbDataHI
            // 
            this.tbDataHI.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.tbDataHI.Location = new System.Drawing.Point(104, 72);
            this.tbDataHI.MaxLength = 4;
            this.tbDataHI.Name = "tbDataHI";
            this.tbDataHI.Size = new System.Drawing.Size(48, 26);
            this.tbDataHI.TabIndex = 10;
            this.tbDataHI.Text = "0000";
            // 
            // tbMaskHI
            // 
            this.tbMaskHI.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.tbMaskHI.Location = new System.Drawing.Point(104, 120);
            this.tbMaskHI.MaxLength = 4;
            this.tbMaskHI.Name = "tbMaskHI";
            this.tbMaskHI.Size = new System.Drawing.Size(48, 26);
            this.tbMaskHI.TabIndex = 9;
            this.tbMaskHI.Text = "0000";
            // 
            // tbAddressLO
            // 
            this.tbAddressLO.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.tbAddressLO.Location = new System.Drawing.Point(160, 24);
            this.tbAddressLO.MaxLength = 4;
            this.tbAddressLO.Name = "tbAddressLO";
            this.tbAddressLO.Size = new System.Drawing.Size(48, 26);
            this.tbAddressLO.TabIndex = 8;
            this.tbAddressLO.Text = "0000";
            // 
            // tbDataLO
            // 
            this.tbDataLO.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.tbDataLO.Location = new System.Drawing.Point(160, 72);
            this.tbDataLO.MaxLength = 4;
            this.tbDataLO.Name = "tbDataLO";
            this.tbDataLO.Size = new System.Drawing.Size(48, 26);
            this.tbDataLO.TabIndex = 7;
            this.tbDataLO.Text = "0000";
            // 
            // tbMaskLO
            // 
            this.tbMaskLO.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.tbMaskLO.Location = new System.Drawing.Point(160, 120);
            this.tbMaskLO.MaxLength = 4;
            this.tbMaskLO.Name = "tbMaskLO";
            this.tbMaskLO.Size = new System.Drawing.Size(48, 26);
            this.tbMaskLO.TabIndex = 6;
            this.tbMaskLO.Text = "0000";
            // 
            // lbAddress
            // 
            this.lbAddress.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.lbAddress.Location = new System.Drawing.Point(0, 32);
            this.lbAddress.Name = "lbAddress";
            this.lbAddress.Size = new System.Drawing.Size(96, 24);
            this.lbAddress.Text = "Address:";
            this.lbAddress.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // lbData
            // 
            this.lbData.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.lbData.Location = new System.Drawing.Point(0, 80);
            this.lbData.Name = "lbData";
            this.lbData.Size = new System.Drawing.Size(96, 24);
            this.lbData.Text = "Data:";
            this.lbData.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // lbMask
            // 
            this.lbMask.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.lbMask.Location = new System.Drawing.Point(0, 128);
            this.lbMask.Name = "lbMask";
            this.lbMask.Size = new System.Drawing.Size(96, 24);
            this.lbMask.Text = "Mask:";
            this.lbMask.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // vScrollBar1
            // 
            this.vScrollBar1.LargeChange = 16;
            this.vScrollBar1.Location = new System.Drawing.Point(208, 16);
            this.vScrollBar1.Maximum = 32;
            this.vScrollBar1.Minimum = -32;
            this.vScrollBar1.Name = "vScrollBar1";
            this.vScrollBar1.Size = new System.Drawing.Size(13, 40);
            this.vScrollBar1.SmallChange = 4;
            this.vScrollBar1.TabIndex = 2;
            this.vScrollBar1.ValueChanged += new System.EventHandler(this.vScrollBar1_ValueChanged);
            // 
            // lbHI
            // 
            this.lbHI.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.lbHI.Location = new System.Drawing.Point(120, 0);
            this.lbHI.Name = "lbHI";
            this.lbHI.Size = new System.Drawing.Size(32, 20);
            this.lbHI.Text = "HI";
            // 
            // lbLO
            // 
            this.lbLO.Font = new System.Drawing.Font("Courier New", 10.2F, System.Drawing.FontStyle.Regular);
            this.lbLO.Location = new System.Drawing.Point(176, 0);
            this.lbLO.Name = "lbLO";
            this.lbLO.Size = new System.Drawing.Size(32, 20);
            this.lbLO.Text = "LO";
            // 
            // Form1
            // 
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
            this.ClientSize = new System.Drawing.Size(638, 455);
            this.Controls.Add(this.lbLO);
            this.Controls.Add(this.lbHI);
            this.Controls.Add(this.vScrollBar1);
            this.Controls.Add(this.lbMask);
            this.Controls.Add(this.lbData);
            this.Controls.Add(this.lbAddress);
            this.Controls.Add(this.tbMaskLO);
            this.Controls.Add(this.tbDataLO);
            this.Controls.Add(this.tbAddressLO);
            this.Controls.Add(this.tbMaskHI);
            this.Controls.Add(this.tbDataHI);
            this.Controls.Add(this.tbAddressHI);
            this.Controls.Add(this.btWrite);
            this.Controls.Add(this.btRead);
            this.MaximizeBox = false;
            this.Name = "Form1";
            this.Text = "PHYIO V1.1";
            this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
            this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>

		static void Main() 
		{
			Application.Run(new Form1());
		}

		private void btRead_Click(object sender, System.EventArgs e)
		{
			int	cb	= 0;
			byte[] inbuffer = new byte[8];
			byte[] outbuffer = new byte[4];


			if (!verifyAddressParameter())
			{
				reWriteAddressParameter();
				return;
			}
 
			inbuffer[0] = 1;

			//address
			outbuffer = BitConverter.GetBytes(g_address);
			inbuffer[7] = outbuffer[3];
			inbuffer[6] = outbuffer[2];
			inbuffer[5] = outbuffer[1];
			inbuffer[4] = outbuffer[0];

			if (!KernelIoControl(IOCTL_PHY_ADR, inbuffer, 8, outbuffer, 4, ref cb))
			{
				MessageBox.Show ("KernelIoControl call error! ","Access error",
					MessageBoxButtons.OK, MessageBoxIcon.Exclamation,MessageBoxDefaultButton.Button1);
				return;
			}
			g_data = BitConverter.ToUInt32(outbuffer,0);
			reWriteAddressParameter();
			reWriteDataParameter();
		}

		private void btWrite_Click(object sender, System.EventArgs e)
		{
			int	cb	= 0;
			byte[] inbuffer = new byte[16];
			byte[] outbuffer = new byte[4];

			if (!verifyAddressParameter())
			{
				reWriteAddressParameter();
				return;
			}
			if (!verifyDataParameter())
			{
				reWriteDataParameter();
				return;
			}
			if (!verifyMaskParameter())
			{
				reWriteMaskParameter();
				return;
			}

			inbuffer[0] = 2;

			//address
			outbuffer = BitConverter.GetBytes(g_address);
			inbuffer[7] = outbuffer[3];
			inbuffer[6] = outbuffer[2];
			inbuffer[5] = outbuffer[1];
			inbuffer[4] = outbuffer[0];
			//data
			outbuffer = BitConverter.GetBytes(g_data);
			inbuffer[11] = outbuffer[3];
			inbuffer[10] = outbuffer[2];
			inbuffer[9] = outbuffer[1];
			inbuffer[8] = outbuffer[0];
			//mask
			outbuffer = BitConverter.GetBytes(g_mask);
			inbuffer[15] = outbuffer[3];
			inbuffer[14] = outbuffer[2];
			inbuffer[13] = outbuffer[1];
			inbuffer[12] = outbuffer[0];
			if (!KernelIoControl(IOCTL_PHY_ADR, inbuffer, 16, outbuffer, 4, ref cb))
			{
				MessageBox.Show ("KernelIoControl call error! ","Access error",
					MessageBoxButtons.OK, MessageBoxIcon.Exclamation,MessageBoxDefaultButton.Button1);
				return;
			}
			reWriteAddressParameter();
			reWriteDataParameter();
			reWriteMaskParameter();
		}

		private void reWriteAddressParameter()
		{
			string output;

			output = String.Format("{0:X4}", g_address>>16);
			tbAddressHI.Text = output;
			output = String.Format("{0:X4}", (g_address & 0x0000ffff));
			tbAddressLO.Text = output;
		}

		private bool verifyAddressParameter()
		{
			UInt16 AddressLO = 0;

			try 
			{
				System.Convert.ToUInt16(tbAddressHI.Text,16);
			}
			catch (System.FormatException)
			{
				return false;
			}
			catch (System.OverflowException)
			{
				return false;
			}
			try 
			{
				AddressLO = System.Convert.ToUInt16(tbAddressLO.Text,16);
			}
			catch (System.FormatException)
			{
				return false;
			}
			catch (System.OverflowException)
			{
				return false;
			}
			// test word boundry
			if (0 != AddressLO % 4)
			{
				MessageBox.Show ("Address error, must be on 4 byte boundry! ","Access error",
					MessageBoxButtons.OK, MessageBoxIcon.Exclamation,MessageBoxDefaultButton.Button1);
				return false;
			}
			try 
			{
				g_address = System.Convert.ToUInt32(tbAddressHI.Text,16) * 0x00010000 +
					System.Convert.ToUInt32(tbAddressLO.Text,16);
			}
			catch (System.FormatException)
			{
				return false;
			}
			return true;
		}

		private void reWriteDataParameter()
		{
			string output;

			output = String.Format("{0:X4}", g_data>>16);
			tbDataHI.Text = output;
			output = String.Format("{0:X4}", (g_data & 0x0000ffff));
			tbDataLO.Text = output;
		}

		private bool verifyDataParameter()
		{
			try 
			{
				System.Convert.ToUInt16(tbDataHI.Text,16);
			}
			catch (System.FormatException)
			{
				return false;
			}
			catch (System.OverflowException)
			{
				return false;
			}
			try 
			{
				System.Convert.ToUInt16(tbDataLO.Text,16);
			}
			catch (System.FormatException)
			{
				return false;
			}
			catch (System.OverflowException)
			{
				return false;
			}
			try
			{
				g_data = System.Convert.ToUInt32(tbDataHI.Text,16) * 0x00010000 +
					System.Convert.ToUInt32(tbDataLO.Text,16);
			}
			catch (System.FormatException)
			{
				return false;
			}
			return true;
		}

		private void reWriteMaskParameter()
		{
			string output;

			output = String.Format("{0:X4}", g_mask>>16);
			tbMaskHI.Text = output;
			output = String.Format("{0:X4}", (g_mask & 0x0000ffff));
			tbMaskLO.Text = output;
		}

		private bool verifyMaskParameter()
		{
			try 
			{
				System.Convert.ToUInt16(tbMaskHI.Text,16);
			}
			catch (System.FormatException)
			{
				return false;
			}
			catch (System.OverflowException)
			{
				return false;
			}
			try 
			{
				System.Convert.ToUInt16(tbMaskLO.Text,16);
			}
			catch (System.FormatException)
			{
				return false;
			}
			catch (System.OverflowException)
			{
				return false;
			}
			try
			{
				g_mask = System.Convert.ToUInt32(tbMaskHI.Text,16) * 0x00010000 +
					System.Convert.ToUInt32(tbMaskLO.Text,16);
			}
			catch (System.FormatException)
			{
				return false;
			}
			return true;
		}

		private void vScrollBar1_ValueChanged(object sender, System.EventArgs e)
		{
			if (verifyAddressParameter() && vScrollBar1.Value != 0)
			{
				switch (vScrollBar1.Value) 
				{
					case 16:
						g_address = g_address - 16;
						break;
					case 4:
						g_address = g_address - 4;
						break;
					case -16:
						g_address = g_address + 16;
						break;
					case -4:
						g_address = g_address + 4;
						break;
				}
				reWriteAddressParameter();
				vScrollBar1.Value = 0;
			}
		}
	}
}
